﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BindableUserControl.cs" company="">
//   
// </copyright>
// <summary>
//   The bindable user control.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.Controls
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Drawing;
	using System.Windows.Forms;
	using Libium.Core;
	using Libium.UseCases;
	using Libium.Views;
	using Libium.WindowsForms.Controls;

    /// <summary>
    /// The bindable user control.
    /// </summary>
    public partial class BindableUserControl : UserControl, IView
    {
        #region Fields

        /// <summary>
        /// The _show only on mouse over controls.
        /// </summary>
        private readonly List<Control> _autoHideControls = new List<Control>();

        /// <summary>
        /// The _capture global mouse.
        /// </summary>
        private bool _captureGlobalMouse;

        /// <summary>
        /// The _global mouse entered.
        /// </summary>
        private bool _globalMouseEntered;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="BindableUserControl"/> class.
        /// </summary>
        protected BindableUserControl()
        {
            InitializeComponent();
            DragHandler = new DragHandler();
            DropHandler = new DropHandler();

				//waitPanel1.Controls.Add(waitCancel);
				waitCancel.Dock = DockStyle.Bottom;
			  
        }

        #endregion

        #region Public Events

        /// <summary>
        /// The focused changed.
        /// </summary>
		  public event Action<IView> FocusedChanged;

		  /// <summary>
		  ///  Cancels wating process.
		  /// </summary>
		  public event Action<IView> WaitCancelled;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets a value indicating whether capture global mouse.
        /// </summary>
        public bool CaptureGlobalMouse
        {
            get
            {
                return _captureGlobalMouse;
            }

            set
            {
                if (_captureGlobalMouse == value)
                {
                    return;
                }

                _captureGlobalMouse = value;
                if (_captureGlobalMouse)
                {
                    MouseMessageFilter.Instance.MouseMove += OnGlobalMouseMove;
                }
                else
                {
                    MouseMessageFilter.Instance.MouseMove -= OnGlobalMouseMove;
                }
            }
        }

        /// <summary>
        /// Gets or sets the copy source.
        /// </summary>
        public ICopySource CopySource
        {
            get
            {
                return DragHandler.Source;
            }

            set
            {
                DragHandler.Source = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether global mouse enabled.
        /// </summary>
        public bool GlobalMouseEnabled
        {
            get
            {
                return MouseMessageFilter.Instance.Enabled;
            }

            set
            {
                MouseMessageFilter.Instance.Enabled = value;
            }
        }

        /// <summary>
        /// Gets or sets the paste target.
        /// </summary>
        public IPasteTarget PasteTarget
        {
            get
            {
                return DropHandler.Target;
            }

            set
            {
                DropHandler.Target = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether read only.
        /// </summary>
        public virtual bool ReadOnly
        {
            get
            {
                return true;
            }

            set
            {
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the drag handler.
        /// </summary>
        protected DragHandler DragHandler { get; private set; }

        /// <summary>
        /// Gets the drop handler.
        /// </summary>
        public DropHandler DropHandler { get; private set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The clear.
        /// </summary>
        public virtual void Clear()
        {
        }

        #endregion

        #region Methods

        /// <summary>
        /// The copy.
        /// </summary>
        protected virtual void Copy()
        {
            var data = CopySource.StartCopy();
            var copyDataObject = new CopyDataObject(data);
            Clipboard.SetDataObject(copyDataObject);
            CopySource.FinishCopy(CopyAction.Copy);
        }

        /// <summary>
        /// The cut.
        /// </summary>
        protected virtual void Cut()
        {
            var data = CopySource.StartCopy();
            var copyDataObject = new CopyDataObject(data);
            Clipboard.SetDataObject(copyDataObject);
            CopySource.FinishCopy(CopyAction.Move);
        }

        /// <summary>
        /// The dispose.
        /// </summary>
        /// <param name="disposing">
        /// The disposing.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            MouseMessageFilter.Instance.MouseMove -= OnGlobalMouseMove;
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            base.Dispose(disposing);
        }

        /// <summary>
        /// The on focused changed.
        /// </summary>
        protected virtual void OnFocusedChanged()
        {
            if (FocusedChanged != null)
            {
                FocusedChanged(this);
            }
        }

        /// <summary>
        /// The on global mouse enter.
        /// </summary>
        protected virtual void OnGlobalMouseEnter()
        {
            foreach (Control control in _autoHideControls)
            {
                control.Visible = true;
            }
        }

        /// <summary>
        /// The on global mouse leave.
        /// </summary>
        protected virtual void OnGlobalMouseLeave()
        {
            foreach (Control control in _autoHideControls)
            {
                control.Visible = false;
            }
        }

        /// <summary>
        /// The on global mouse move.
        /// </summary>
        /// <param name="point">
        /// The point.
        /// </param>
        protected virtual void OnGlobalMouseMove(Point point)
        {
			  if (!IsDisposed)
            {
                var rectangle = RectangleToScreen(ClientRectangle);
                if (rectangle.Contains(point))
                {
                    OnLocalMouseMove(PointToClient(point));
                    if (!_globalMouseEntered)
                    {
                        _globalMouseEntered = true;
                        OnGlobalMouseEnter();
                    }
                }
                else
                {
                    if (_globalMouseEntered)
                    {
                        _globalMouseEntered = false;
                        OnGlobalMouseLeave();
                    }
                }
            }
            else
            {
                MouseMessageFilter.Instance.MouseMove -= OnGlobalMouseMove;
            }
        }

        /// <summary>
        /// The on got focus.
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            OnFocusedChanged();
        }

        /// <summary>
        /// The on local mouse move.
        /// </summary>
        /// <param name="point">
        /// The point.
        /// </param>
        protected virtual void OnLocalMouseMove(Point point)
        {
        }

        /// <summary>
        /// The on lost focus.
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            OnFocusedChanged();
        }

        /// <summary>
        /// The on visible changed.
        /// </summary>
        /// <param name="e">
        /// The e.
        /// </param>
        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            if (Visible)
            {
                if (_captureGlobalMouse)
                {
                    MouseMessageFilter.Instance.MouseMove += OnGlobalMouseMove;
                }
            }
            else
            {
                if (_captureGlobalMouse)
                {
                    MouseMessageFilter.Instance.MouseMove -= OnGlobalMouseMove;
                }
            }
        }

        /// <summary>
        /// The paste.
        /// </summary>
        protected virtual void Paste()
        {
            var copyData = new PasteDataObject(Clipboard.GetDataObject());
            PasteTarget.Paste(copyData, CopyAction.Copy);
        }

        /// <summary>
        /// The show only on mouse over.
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        protected void SetAutoHide(Control control, bool value)
        {
            if (value)
            {
                _autoHideControls.Add(control);
                CaptureGlobalMouse = true;
                control.Visible = false;
            }
            else
            {
                _autoHideControls.Remove(control);
                if (_autoHideControls.Count == 0)
                {
                    CaptureGlobalMouse = false;
                }
                control.Visible = true;
            }
        }

        protected bool GetAutoHide(Control control)
        {
            return _autoHideControls.Contains(control);
        }

        /// <summary>
        /// The context menu_ opening.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ContextMenu_Opening(object sender, CancelEventArgs e)
        {
            var copyData = new PasteDataObject(Clipboard.GetDataObject());
            var copyOptions = CopySource.GetCopyOptions();
            var pasteOptions = PasteTarget.GetPasteOptions(copyData);
            CopyMenuItem.Enabled = copyOptions.CanCopy;
            CutMenuItem.Enabled = copyOptions.CanMove;
            PasteMenuItem.Enabled = pasteOptions.CanCopy;
        }

        /// <summary>
        /// The copy menu item_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void CopyMenuItem_Click(object sender, EventArgs e)
        {
            Copy();
        }

        /// <summary>
        /// The cut menu item_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void CutMenuItem_Click(object sender, EventArgs e)
        {
            Cut();
        }

        /// <summary>
        /// The on global mouse move.
        /// </summary>
        private void OnGlobalMouseMove()
        {
            if (_captureGlobalMouse)
            {
                OnGlobalMouseMove(Cursor.Position);
            }
        }

        /// <summary>
        /// The paste menu item_ click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void PasteMenuItem_Click(object sender, EventArgs e)
        {
            Paste();
        }

		  public virtual void AddWarning(string warning)
		  {
		  }

		  public virtual void RemoveWarning()
		  {
		  }

		  public virtual void AddError(string warning)
		  {
		  }

		  public virtual void RemoveError()
		  {
		  }

		  public virtual void AddHint(string warning)
		  {
		  }

		  public virtual void RemoveHint()
		  {
		  }

		  /*public virtual void OnDragEnter(object sender, DragEventArgs dragEventArgs)
		  {
			  BindableUserControl bindableParent = ((Control)sender).Parent as BindableUserControl;
			  if (bindableParent != null)
				  bindableParent.OnDragEnter(sender, dragEventArgs);
		  }*/

		  public void StartWait(IUseCase useCase)
		  {
              //TODO add wait panel
			  //waitPanel1.Show("Please wait...");
			  //waitPanel1.Enabled = true;
			  foreach (Control c in this.Controls)
			  {
				  //if (c != waitPanel1)
				  //{
					//  c.Enabled = false;
				  //}
			  }
		  }

		  public void EndWait(IUseCase useCase)
		  {
			  //waitPanel1.Hide();
			  foreach (Control c in this.Controls)
			  {
                  //if (c != waitPanel1)
                  //{
                  //    c.Enabled = true;
                  //}
			  }
		  }

		  public void SetWaitProgress(IUseCase useCase)
		  {

		  }
        #endregion

		  private void waitCancel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		  {
			  if (WaitCancelled != null)
			  {
				  WaitCancelled(this);
			  }
		  }
    }
}